/* UTF8 Encoding */
/*-----------------------------------------------------------------------
|                            FILE DESCRIPTION                           |
-----------------------------------------------------------------------*/
/*----------------------------------------------------------------------
  - File name     : at_aithinker_combo.h
  - Author        : liuzhihua (liuzhihuawy@163.com)
  - Update date   : 2024.08.31
  - Brief         : at command for aithinker combo
  - Version       : v0.2
-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------
|                               UPDATE NOTE                             |
-----------------------------------------------------------------------*/
/**
  * Update note:
  * ------------   ---------------   ----------------------------------
  *     Date            Author                      Note
  * ------------   ---------------   ----------------------------------
  *  2024.08.20       liuzhihua                  Create file          
  *  2024.08.31       liuzhihua             add subscribe callback          
***/

#ifndef __AT_AITHINKER_COMBO_H
#define __AT_AITHINKER_COMBO_H

/*-----------------------------------------------------------------------
|                               INCLUDES                                |
-----------------------------------------------------------------------*/
#include "at_base.h"
#include <stdio.h>
#include <stdint.h>
#include "bsp_uart.h"
/*-----------------------------------------------------------------------
|                                DEFINES                                |
-----------------------------------------------------------------------*/
#define ATDebugPrintf(str, ...) UARTx_Printf(&huart1, str, ##__VA_ARGS__)


class AT_AiCombo : public ATBase
{
public:
    const static int CMD_BUFFER_SIZE = 12;
    AT_AiCombo(int (*send_data_fn)(const uint8_t * pdata, uint16_t size));
    virtual int cmd_send(const uint8_t *txdata, uint16_t size);

    enum CMD_ID
    {
        CMDID_RESET = 1,
        CMDID_SET_WMODE,
        CMDID_GET_WMODE,
        CMDID_JOIN_AP,
        CMDID_GET_APSTATE,
        CMDID_CREATE_AP,
        CMDID_MQTT_CFG_HOST,
        CMDID_MQTT_CFG_PORT,
        CMDID_MQTT_CFG_TYPE,
        CMDID_MQTT_CFG_CLIENTID,
        CMDID_MQTT_CFG_USERNAME,
        CMDID_MQTT_CFG_PWD,
        CMDID_MQTT_CONNECT,
        CMDID_MQTT_DISCONNECT,
        CMDID_MQTT_PUBLISH,
        CMDID_MQTT_SUBSCRIBE,
    };
    static const char REPLY_STRING_OK[3];
    static const char REPLY_STRING_ERROR[6];
    static const char REPLY_STRING_EVENT[6];

    typedef enum AiCombo_WifiMode_Typedef
    {
        WMODE_NONE = 0, // 未初始化或者关闭Wi-Fi
        WMODE_STATION = 1, // STA模式,可以连wifi
        WMODE_AP = 2, // AP模式,可以创建wifi
        WMODE_STA_AP = 3, // STA+AP模式,可以连wifi,也可以创建wifi
        WMODE_NONE_SAVE = 4, // 未初始化或者关闭Wi-Fi
        WMODE_STATION_SAVE = 5, // STA模式,可以连wifi,并且保存到flash
        WMODE_AP_SAVE = 6, // AP模式,可以创建wifi,并且保存到flash
        WMODE_STA_AP_SAVE = 7, // STA+AP模式,可以连wifi,也可以创建wifi,并且保存到flash
    } wmode_t;
    typedef enum AiCombo_APState_Typedef
    {
        // 0：没有连接Wi-Fi(初始状态或者STA模式没有开启)
        APSTATE_NONE = 0,
        // 1：正在连接Wi-Fi或者Wi-Fi重连中
        APSTATE_JOINING = 1,
        // 2：连接了Wi-Fi，还没有获取到IP
        APSTATE_GETIP = 2,
        // 3：连接到Wi-Fi，并且已经获取到了IP
        APSTATE_OK = 3,
        // 4：Wi-Fi连接失败（超过了重连次数还没有连接成功的状态）
        APSTATE_FAILED = 4,
    } ap_state_t;

    /*
+WJAP:<status>,<ssid>,<pwd>,<bssid>,<Security>,<MAC>,<ch>,<IP>,<gateway>
Client Num: <client number>
Client <id> MAC:
OK
    */
    typedef struct AiCombo_APInfo_Typedef
    {
        ap_state_t status;
        char ssid[33];      // wifi ssid
        char pwd[33];       // wifi password
        char bssid[18];     // <xx:xx:xx:xx:xx:xx> [17 char] + [1 '\0']
        uint8_t security;
        char mac[18];       // <xx:xx:xx:xx:xx:xx> [17 char] + [1 '\0']
        char channel[4];
        char ip[16];        // <xxx.xxx.xxx.xxx> [15 char] + [1 '\0']
        char gateway[16];
    } ap_info_t;

    typedef struct AiCombo_MQTT_Topic_Typedef
    {
        const char *pstr;
        uint16_t id;
        uint8_t qos;
        bool retained; // 0：普通消息 ,1：Retained消息
    } mqtt_topic_t;
    
    typedef struct AiCombo_MQTTConfig_Typedef
    {
        const char *host;          // 服务器地址
        const char *port;          // 服务器端口
        const char *client_id;     // 客户端ID
        const char *username;      // 用户名
        const char *password;      // 密码
        mqtt_topic_t *topicsub; // 订阅的主题
        uint8_t topicsub_num;   // 主题数量
        void (*subscribe_callback)(uint16_t id, const uint8_t *pPayload, uint16_t len); // 回调函数
    } mqtt_cfg_t;

    wmode_t wmode;             // wifi模式
    ap_info_t ap_info;         // ap信息
    mqtt_cfg_t *mqtt_cfg;      // mqtt配置信息
    bool mqtt_state;           // 0:未连接, 1:已连接

private:
    static int reply_check_ok(void * arg, const ATBase::at_cmd_t *pCmd, uint32_t events);
    at_cmd_t cmd_buffer[CMD_BUFFER_SIZE]; // 命令缓冲区
    int (*send_data_fn)(const uint8_t * pdata, uint16_t size); // 回调函数
public:
    void receive_handle(const uint8_t * pdata, uint16_t size);
    /*------------- 设备操作 -------------*/
    bool reset(void);

    /*------------ WiFi 操作 ------------*/
    bool set_wmode(wmode_t mode);
    bool request_wmode(void);

    bool join_ap(const char *ssid, const char *pwd, const char *bssid = NULL);
    bool request_ap_state(void);

    bool create_ap(const char *ssid, const char *pwd, const char *bssid = NULL); // TODO: 创建AP

    bool get_network_state(void);
    bool get_broadcast_ip(char buffer[16]) const;

    /*------------ MQTT操作 ------------*/
    bool mqtt_connect(mqtt_cfg_t *pMqttCfg);
    bool mqtt_disconnect(void);
    bool mqtt_publish(const char *pTopic, const char *pPayload, uint8_t qos = 0, bool retained = 0);
    bool mqtt_subscribe(void);

};


/*-----------------------------------------------------------------------
|                                  API                                  |
-----------------------------------------------------------------------*/

#ifdef  __cplusplus
    extern "C" {
#endif

#ifdef __cplusplus
	}
#endif
#endif
